(require 'org-install)
;(require 'org-refile-immediate-target)

;; The following lines are always needed.  Choose your own keys.
(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode))

;; Based on:
;;  http://doc.norang.ca/org-mode.html
(setq org-todo-keywords
      (quote ((sequence
	       "TODO(t)"
	       "NEXT(n)"
	       "STARTED(s)"
	       "WAITING(w@/!)"
	       "SOMEDAY(z)"
	       "|"
	       "DONE(d!/!)"
	       "CANCELLED(c@/!)"))))

(setq org-tag-alist
      '(
	("desk" . ?d)
	("work" . ?w)
	("garden" . ?g)
	("errands" . ?e)
	("basement" . ?b)
	("kitchen" . ?k)
	("Net" . ?n)
	("leisure" . ?l)
	("Toronto" . ?t)
	))

(global-set-key (kbd "C-c l") 'org-store-link)
(global-set-key (kbd "C-c a") 'org-agenda)
(global-set-key (kbd "C-c c") 'org-iswitchb)

(cond
 ((string-match "shodan.wat" system-name) (setq org-directory "~/org/"))
 ((string-match "sovereign" system-name) (setq org-directory "~/Google Drive/org/")))

(setq org-default-notes-file (concat org-directory "capture.org"))
(setq org-use-speed-commands t)
(setq org-completion-use-ido t)
(setq org-return-follows-link t)
;(setq org-blank-before-new-entry '((heading nil) (plain-list-item . nil)))
(setq org-blank-before-new-entry nil)
(setq org-startup-folded 'content)
(setq org-special-ctrl-a t)
(setq org-special-ctrl-e t)
(setq org-special-ctrl-k nil)
(setq org-agenda-span 3)
(setq org-agenda-start-on-weekday nil)
(setq org-reverse-note-order t)

(setq org-refile-targets (quote (
				 ("buy.org" :maxlevel . 1)
				 ("corp.org" :maxlevel . 1)
				 ("gtd.org" :maxlevel . 1)
				 ("self-dev.org" :maxlevel . 1)
				 ("someday.org" :maxlevel . 1)
				 )))

(cond
 ((string-match "sovereign" system-name)
  (custom-set-variables
   '(org-agenda-files (list (concat org-directory "buy.org")
			    (concat org-directory "gtd.org")
			    (concat org-directory "self-dev.org")
			    (concat org-directory "corp.org")
			    (concat org-directory "projects")
			    (concat org-directory "waiting.org")))))
 ((string-match "shodan.wat" system-name)
  (custom-set-variables
   '(org-agenda-files (list (concat org-directory "gtd.org"))))))

(setq org-capture-templates
      '(("t" "Todo" entry
	 (file+headline (concat org-directory "/capture.org") "Tasks")
	 "* TODO %?\n  %i")
	("T" "Todo w/context" entry
	 (file+headline (concat org-directory "/capture.org") "Tasks")
	 "* TODO %?\n  %i\n  %a")
        ("j" "Journal" entry
	 (file+headline (concat org-directory "/journal.org") "Journal")
	 "* %T\n%?" :prepend t)
	("n" "Note" entry
	 (file+headline (concat org-directory "/notes.org") "inbox")
	 "* %?\n %i")))

;; From:
;;  http://newartisans.com/2007/08/using-org-mode-as-a-day-planner/n
(require 'org-agenda)
(custom-set-variables
 '(org-agenda-custom-commands
   '(("d" "my Daily view" 
      ((agenda "" ((org-agenda-ndays 1))) ;; limits the agenda to single day
       (tags-todo "+PRIORITY=\"A\"")
       (todo "NEXT")
       (tags-todo "computer|office|phone")
       (todo "WAITING"))
      ((org-agenda-compact-blocks nil)))
     ("c" todo "DONE|DEFERRED|CANCELLED" nil)
     ("w" todo "WAITING" nil)
     ("W" agenda "" ((org-agenda-ndays 21)))
     ("A" agenda ""
      ((org-agenda-skip-function
	(lambda nil
	  (org-agenda-skip-entry-if 'notregexp "\\=.*\\[#A\\]")))
       (org-agenda-ndays 1)
       (org-agenda-overriding-header "Today's Priority #A tasks: ")))
     ("u" alltodo ""
      ((org-agenda-skip-function
	(lambda nil
	  (org-agenda-skip-entry-if 'scheduled 'deadline
				    'regexp "\n]+>")))
       (org-agenda-overriding-header "Unscheduled TODO entries: "))))))

;(add-to-list 'org-agenda-custom-commands
;            '("." "Closed this week."
;              tags "CLOSED>\"<-1w>\""
;              ((org-agenda-sorting-strategy '(priority-down)))))

(setq org-global-properties
      '(("Effort_ALL" .
	 "0 0:15 0:30 1:00 2:00 3:00 4:00 5:00 6:00 8:00")))

(setq org-agenda-sorting-strategy '(time-up todo-state-down priority-down))
(setq org-agenda-skip-deadline-if-done t)
(setq org-agenda-skip-scheduled-if-done t)

;; MobileOrg settings
(setq org-mobile-directory "~/Dropbox/Apps/MobileOrg")
(setq org-mobile-inbox-for-pull (concat org-directory "/from-mobile.org"))

;; Use "clean view".
(setq org-startup-indented t)

;; log finish times
(setq org-log-done 'time)

(global-set-key (kbd "C-c r") 'org-capture)
(global-set-key (kbd "C-c a") 'org-agenda)
(global-set-key (kbd "C-c n") 'mk/org-goto-now)
(global-set-key (kbd "C-c N") 'mk/org-empty-now)
(global-set-key (kbd "C-c e") 'mk/org-empty-to-today)

(defun mk/org-goto-section (section)
  "Go to the named section."
  (goto-char (point-min))
  (search-forward-regexp (concat "^\\* " section)))

(defun mk/org-goto-now ()
  "Go to the first item of @now section."
  (interactive)
  (mk/org-goto-section "@now")
  (next-line)
  (move-beginning-of-line 1))

(define-key global-map "\C-cg" (lambda ()
			  (interactive)
			  (find-file (concat org-directory "gtd.org"))))

(defun mk/org-get-todo-keyword-value ()
  (if (looking-at org-complex-heading-regexp)
      (- 9999 (length (member (match-string 2)
			      org-todo-keywords-1)))))

(defun mk/org-resort-todos ()
  (interactive)
  (save-excursion
    (outline-up-heading 10)
    (org-sort-entries t ?p)
    (org-sort-entries t ?F 'mk/org-get-todo-keyword-value)
    (org-overview)
    (org-cycle))
  ; TODO: bound it to not exceed the end of sorted text.
  (search-forward-regexp "\\* \\(STARTED\\|NEXT\\|TODO\\)")
  (move-beginning-of-line 1)
)

; Some ideas:
; http://stackoverflow.com/questions/7509463/how-to-move-a-subtree-to-another-subtree-in-org-mode-emacs
; http://superuser.com/questions/613968/how-to-automate-org-refile-for-multiple-todo

; still not working right
(defun mk/org-empty-now ()
  (interactive)
  (mk/org-goto-now)
  (org-mark-subtree 1)
  (next-line)
  (kill-region (point) (mark))

  (mk/org-goto-section "@today")
  (next-line)
  (move-beginning-of-line 1)
  (yank)
)

(defun mk/org-empty-to-today ()
  (interactive)
  (outline-up-heading 9)
  (org-mark-subtree 1)
  (next-line)
  (kill-region (point) (mark))

  (mk/org-goto-section "@today")
  (show-children)
  (next-line)
  (move-beginning-of-line 1)
  (yank)
)

(eval-after-load "org"
  (add-hook 'org-load-hook
	    (lambda ()
	      (define-key org-mode-map (kbd "C-c g") 'mk/org-resort-todos))))

;; TODO does this actually work?
(fset 'refile-to-same
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([3 23 return] 0 "%d")) arg)))
(define-key org-mode-map (kbd "C-c f") 'refile-to-same)
